#ifdef COMPILE_OPENGL

#include "CBL_Defines.h"

#ifdef CB_MACOSX

#include "CBL_Memory.h"
#include "COGL_Native.h"
#include "COGL_Context.h"
#include "COGL_PixelBufferAtomic.h"
#include "COGL_Extensions.h"
#include "COGL_ContextFactory.h"

#include <OpenGL/OpenGL.h>
#import <Cocoa/Cocoa.h>

CB_SUBNAMESPACE_START(OpenGL)

#define ENUM_ITEM(_Name, _Size, _Components, _Flags, _OpenGLFormat, _D3D9Format, _D3D10Format) _Size,
static GLenum s_PixelBufferSize[RenderLib::SPixelFormat::NumFormats] =
{
	#include "CRL_PixelBufferFormatsEnum.h"
};
#undef ENUM_ITEM

// ------------------------------------------------------------------------------------------------------

RenderLib::IContext* CreateMainContext(OpenGL::CContextFactory::CNativeHandle& _rHandle, void*& _rpSystemContext)
{
	NSOpenGLContext* pContext = (NSOpenGLContext*)_rpSystemContext;
    
    if (pContext != nil)
    {
    	[pContext release];
    	_rpSystemContext = NULL;
	}
    
    // Define PixelFormat for OSX Context
    
	int AttrIdx = 0;
	NSOpenGLPixelFormatAttribute PixelAttr[32];
    memset(PixelAttr, 0, sizeof(PixelAttr));
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDoubleBuffered)
        PixelAttr[AttrIdx++] = NSOpenGLPFADoubleBuffer;
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderThreadSafe)
    	PixelAttr[AttrIdx++] = NSOpenGLPFAMPSafe;
    
    if ((_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDoNotUseHardware) == 0)
    	PixelAttr[AttrIdx++] = NSOpenGLPFAAccelerated;
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderFullScreen)
    {
    	PixelAttr[AttrIdx++] = NSOpenGLPFAFullScreen;
    	PixelAttr[AttrIdx++] = NSOpenGLPFAScreenMask;
    	PixelAttr[AttrIdx++] = CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay);
    }
    else
    {
        PixelAttr[AttrIdx++] = NSOpenGLPFAWindow;
    }
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderMultiSamplingEnabled)
    {
        PixelAttr[AttrIdx++] = NSOpenGLPFAMultisample;
        PixelAttr[AttrIdx++] = NSOpenGLPFASampleAlpha;
        PixelAttr[AttrIdx++] = NSOpenGLPFASampleBuffers;
        PixelAttr[AttrIdx++] = 1;
        PixelAttr[AttrIdx++] = NSOpenGLPFASamples;
        PixelAttr[AttrIdx++] = _rHandle.m_MultiSamplingQuality;
	}
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDeferredMainContextColor == 0)
    {
        PixelAttr[AttrIdx++] = NSOpenGLPFAColorSize;
        PixelAttr[AttrIdx++] = s_PixelBufferSize[_rHandle.m_ColorBufferFormat];
    }
    else
    {
    	PixelAttr[AttrIdx++] = NSOpenGLPFAColorSize;
    	PixelAttr[AttrIdx++] = 0;
    }
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDeferredMainContextDepth == 0)
    {
    	PixelAttr[AttrIdx++] = NSOpenGLPFADepthSize;
    	PixelAttr[AttrIdx++] = s_PixelBufferSize[_rHandle.m_DepthBufferFormat];
    }
    else
    {
    	PixelAttr[AttrIdx++] = NSOpenGLPFADepthSize;
    	PixelAttr[AttrIdx++] = 0;
    }
    
    PixelAttr[AttrIdx++] = NSOpenGLPFAPixelBuffer;
    
    PixelAttr[AttrIdx++] = NSOpenGLPFAStencilSize;
    PixelAttr[AttrIdx++] = _rHandle.m_StencilSize;
    
    PixelAttr[AttrIdx++] = NSOpenGLPFAAccumSize;
    PixelAttr[AttrIdx++] = 0;
    
    // Create OSX Context and test
    
    NSOpenGLPixelFormat* pPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: PixelAttr]; 
    pContext = [[NSOpenGLContext alloc] initWithFormat: pPixelFormat shareContext: NULL];
    
    [pPixelFormat release];
    
    if (Debug::Verify(pContext != nil, "Could not create OpenGL context."))
    {
    	if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderFullScreen)
        {
        	CGDisplayErr Error = CGCaptureAllDisplays();
    
    		if (Debug::Verify(Error == CGDisplayNoErr, "Could not capture display. Error %d.", Error)) 
        	{
        		[pContext setFullScreen];
            }
            else
            {
            	[pContext release];
                pContext = nil;
                
                return NULL; // ### return ###
            }
        }
        
        const int SwapInterval = 1;
        
    	[pContext makeCurrentContext];
    	[pContext setValues:&SwapInterval forParameter: NSOpenGLCPSwapInterval];
    	_rpSystemContext = pContext;
    }
    else
    {
		return NULL; // ### return ###
    }
    
    // We now have an active context so get extensions
    
    CExtensions::CreateInstance();
    
    // Create MainContext and buffers if necessary
    
    CContext* pMainContext = new CContext();
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDeferredMainContextColor)
    {
    	RenderLib::CPixelBufferDescriptor ColorBufferDescriptor;
    	
        ColorBufferDescriptor.SetFormat(_rHandle.m_ColorBufferFormat);
        ColorBufferDescriptor.SetWidth(_rHandle.m_BufferWidth);
        ColorBufferDescriptor.SetHeight(_rHandle.m_BufferHeight);
        ColorBufferDescriptor.SetStorageType(RenderLib::CPixelBufferDescriptor::RenderableTexture);
        
        CPixelBufferAtomic* pColorBuffer = new CPixelBufferAtomic(ColorBufferDescriptor);
        
        pMainContext->SetColorTarget(0, RenderLib::CBufferAtomicPtr(pColorBuffer));
    }
    
    if (_rHandle.m_Flags & RenderLib::IPlatformHandle::RenderDeferredMainContextDepth)
    {
    	RenderLib::CPixelBufferDescriptor DepthBufferDescriptor;
        
        DepthBufferDescriptor.SetFormat(_rHandle.m_DepthBufferFormat);
        DepthBufferDescriptor.SetWidth(_rHandle.m_BufferWidth);
        DepthBufferDescriptor.SetHeight(_rHandle.m_BufferHeight);
        DepthBufferDescriptor.SetStorageType(RenderLib::CPixelBufferDescriptor::RenderableTexture);
        
        CPixelBufferAtomic* pDepthBuffer = new CPixelBufferAtomic(DepthBufferDescriptor);
        
        pMainContext->SetDepthTarget(RenderLib::CBufferAtomicPtr(pDepthBuffer));
    }
    
	return pMainContext;
}

CB_SUBNAMESPACE_END

#endif
#endif